package reaction.query;

import java.io.IOException;
import java.util.Map;
import java.util.Set;

import org.apache.lucene.analysis.KeywordAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.queryParser.QueryParser.Operator;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import reaction.news.Definitions;
import reaction.news.index.NewsArticle;
import reaction.utils.xml.XMLUtils;
import reaction.utils.xml.XmlTest;
import reaction.wiki.WikiPT;
import de.tudarmstadt.ukp.wikipedia.api.Page;
import de.tudarmstadt.ukp.wikipedia.api.exception.WikiTitleParsingException;

public class NewsQuery {
		
	public static void main(String[] args) throws Exception {
		
		/* Initialization settings */
		Definitions.init();
		
		XmlTest t = new XmlTest();
		
		String categoria = args[0];
		String id = args[1];	
		
		/* Get last 10 news identifiers
		List<NewsArticle> news = Queries.getNewsIDs();		
		System.out.println(news.size() + " news articles");
		
		/* Get article with NE recognized 
		for (NewsArticle newsArticle : news) {
			newsArticle.xml = XMLUtils.getXML(String.valueOf(newsArticle.id), String.valueOf(newsArticle.category));
			newsArticle.extractNE(newsArticle.pessoas,"PESSOA");
			newsArticle.extractNE(newsArticle.locais,"LOCAL");
			newsArticle.extractNE(newsArticle.organizacoes,"ORGANIZACAO");
			
			t.serialize(newsArticle.xml, System.out);
		}
		*/

		NewsArticle newsArticle = new NewsArticle();
		newsArticle.xml = XMLUtils.getXML(id, categoria);
		
		newsArticle.extractNE(newsArticle.pessoas,"PESSOA");
		newsArticle.extractNE(newsArticle.locais,"LOCAL");
		newsArticle.extractNE(newsArticle.organizacoes,"ORGANIZACAO");

		LinkEntities(newsArticle, false);
		addAttributes(newsArticle,"PESSOA");
		addAttributes(newsArticle,"ORGANIZACAO");
		addAttributes(newsArticle,"LOCAL");

		t.serialize(newsArticle.xml, System.out);

	}
	
	
	public static Document queryLucene(String entity) throws ParseException, IOException {
		
		KeywordAnalyzer analyzer = new KeywordAnalyzer();
		
		QueryParser queryParser = new QueryParser(org.apache.lucene.util.Version.LUCENE_35,"entity", analyzer);
		
		Operator op = org.apache.lucene.queryParser.QueryParser.Operator.AND;
		queryParser.setDefaultOperator(op);
		Query q = queryParser.parse(entity);
		
		TopDocs docs = Definitions.wikipediaSearcher.search(q, 10);
		//System.out.println("total docs: " + docs.totalHits);
		
		ScoreDoc[] scoreDocs = docs.scoreDocs;
		
		for (int i = 0; i < scoreDocs.length; i++) {
			//System.out.print("rank "+(i+1)+'\t'+scoreDocs[i].score+'\t');
			Document d = Definitions.wikipediaSearcher.doc(scoreDocs[i].doc);
			//System.out.println("entity: " + d.get("entity"));
			//System.out.println("plaintTitled: " + d.get("plaintTitle"));
			//System.out.println("URL: " + d.get("URL"));
			//System.out.println("categories: " + d.get("categories"));
			//System.out.println("wiki_text: " + d.get("wiki_text"));
		}
		if (docs.totalHits>0)
			return Definitions.wikipediaSearcher.doc(scoreDocs[0].doc);
		else return null;
	}
	
	
	public static void addAttributes(NewsArticle article, String etype) {
	
		NodeList entities = article.xml.getElementsByTagName(etype);
		Map<String,String> urls = null;
		
		if (etype.equalsIgnoreCase("PESSOA"))
			urls = article.pessoas;
		
		else if (etype.equalsIgnoreCase("ORGANIZACAO"))
			urls = article.organizacoes;
		
		else if (etype.equalsIgnoreCase("LOCAL"))
			urls = article.locais;
			
		for (int i = 0; i < entities.getLength(); i++) {
			
			Node n = entities.item(i);			
			String url = urls.get(n.getTextContent());
			if (!url.isEmpty())
				((Element) n).setAttribute("wikipedia", url);
		}		
	}
	
	
	public static void LinkEntities(NewsArticle article, boolean wiki) throws Exception {
		
		if (wiki) {
			MapEntitiesWiki(article, article.pessoas);
			MapEntitiesWiki(article, article.organizacoes);
			MapEntitiesWiki(article, article.locais);
		}
		else {
			MapEntitiesLucene(article, article.pessoas);
			MapEntitiesLucene(article, article.organizacoes);
			MapEntitiesLucene(article, article.locais);
		}
		
	}
	
	static void MapEntitiesLucene(NewsArticle article, Map<String,String> entitiesMap) throws ParseException, IOException {
		Set<String> entities = entitiesMap.keySet();
		
		for (String entity: entities) {
			Document d = null;
			d = queryLucene('"' + entity + '"');
			
			if (d!=null) {
					String URL = "http://pt.wikipedia.org/wiki/"+d.get("URL");					
					entitiesMap.put(entity, URL);
			}				
		}
	}

	
	static void MapEntitiesWiki(NewsArticle article, Map<String,String> entitiesMap) {
		
		Set<String> entities = entitiesMap.keySet();
		
		for (String entity: entities) {
			
			Page entityPage = WikiPT.getPage(entity);
			
			if (entityPage!=null) {
				
				try {
					
					String URL = "http://pt.wikipedia.org/wiki/"+entityPage.getTitle().getWikiStyleTitle();					
					entitiesMap.put(entity, URL);
					
				} catch (WikiTitleParsingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}				
			}
		}
	}
}







